package com.yfbao.horizon.demo;

import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.yfbao.horizon.cache.vo.CacheVo;
import com.yfbao.horizon.utils.LockUtils;
import lombok.extern.slf4j.Slf4j;

import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

@Slf4j
public class MutilCacheLoad  {

    private static Set<String> loadCacheKeySet = Collections.synchronizedSet(new HashSet<String>());
    private  static ExecutorService executorService = Executors.newFixedThreadPool(10);
    private static Cache<String, Object> localCache = Caffeine.newBuilder().expireAfterWrite(10, TimeUnit.MINUTES).maximumSize(10000).build();

    public static void main(String[] args) {

//        mutilTask();
        cacheTest();
    }

    private static void cacheTest(){
        localCache.put("a","");
        localCache.put("b",new CacheVo());

        Set<String> keySet = localCache.asMap().keySet();
        for (String s : keySet) {
            Object a = localCache.getIfPresent(s);
            if(a.equals("")){
                System.out.println(s+"：empty");
            }else {
                System.out.println(String.valueOf(a));
            }
        }

    }

    private static void mutilTask(){
        String appKey="bpm";
        for(int i=0;i<1000;i++){
            executorService.submit(()->{
                load(appKey);
                Random random =new Random();
                int num = random.nextInt(100);
                if(num>50){
                    localCache.invalidate(appKey);
                }
            });
        }
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        Object ifPresent = localCache.getIfPresent(appKey);
        System.out.println("this:"+ifPresent);
    }

    private static void load(String appKey){
        if(loadCacheKeySet.contains(appKey)){
            log.info("已存在缓存加载队列，本次跳过："+appKey);
            return;
        }
        loadCacheKeySet.add(appKey);
        executorService.submit(()->{
            //加载成功后，从队列移除对应的租户的appid
            loadCacheKeySet.remove(appKey);
            log.info("remove appCacheKey:"+appKey);
            //抢锁
            String lockKey = appKey;
            log.info("appCache load lock key: {}", lockKey);
            boolean locked = false;
            try {
                Object total = localCache.getIfPresent(appKey);
                if (total != null) {
                    log.info("check cache exist:" + appKey);
                    return;
                }

                Thread.sleep(1000);
                locked = LockUtils.tryLock(lockKey, 100);
                //dubbo-check
                Object dubboCheck = localCache.getIfPresent(appKey);
                if (dubboCheck != null) {
                    log.info("double check cache exist:" + appKey);
                    return;
                }
                //加载缓存
                Thread.sleep(200);
                localCache.put(appKey, new Object());
            } catch (InterruptedException e) {
                log.error("", e);
            } finally {
                try {
                    if (locked) {
                        LockUtils.releaseLock(lockKey);
                    }
                } catch (Throwable t) {
                }

            }

        });
    }


}
